/*
********************************************************************************
*
*
********************************************************************************
*/
#include "bsp_hal.h"
#include "sys_ext.h"
#include "com_obj.h"

#define APP_TIM        TMR4
#define app_timer_isr  TMR4_GLOBAL_IRQHandler
#define APP_TIM_IRQn   TMR4_GLOBAL_IRQn
#define APP_TIM_PERIOD 1000

/******************************************************************************
*	                            function
*******************************************************************************/
uint32_t app_tick_init (uint32_t TickPriority);
void app_tick_suspend(void);
void app_tick_resume(void);
uint32_t app_tick_get(void);
uint32_t app_tick_us_get(void);
void app_tick_isr(void);

/******************************************************************************
*	                            var
*******************************************************************************/
volatile uint32_t hal_tick_cnt = 0;
vtask_vector_type app_tick_task_list;

/*******************************************************************************
* @brief  app_tick_init
* \param[in] none
* \retval: none
*******************************************************************************/
uint32_t app_tick_init (uint32_t TickPriority)
{
    RCC_ClockType RCC_Clocks;
    intx_alloc();
    
    intx_disable();
    
    RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_TMR4, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1PERIPH_TMR4, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1PERIPH_TMR4, DISABLE);
    
    intx_enable();
    
    APP_TIM->CTRL1 = TMR_CTRL1_UVERS;
    APP_TIM->CTRL2 = 0;
    APP_TIM->SMC  = 0;
    
    APP_TIM->CC1 = 0;
    APP_TIM->CC2 = 0;
    APP_TIM->CC3 = 0;
    APP_TIM->CC4 = 0;
    
    APP_TIM->CCM1 = 0x6868;
    APP_TIM->CCM2 = 0x6868;    
    APP_TIM->CCE = TMR_CCE_C1EN | TMR_CCE_C2EN | TMR_CCE_C3EN | TMR_CCE_C4EN 
                 | TMR_CCE_C1P | TMR_CCE_C2P | TMR_CCE_C3P | TMR_CCE_C4P;
    
    
    APP_TIM->DIE = 0;
    APP_TIM->STS = 0;
    
    /*1ms interrupt*/
    RCC_GetClocksFreq(&RCC_Clocks);
    APP_TIM->DIV = (RCC_Clocks.APB1CLK_Freq / 1000000) * 2 - 1;
    APP_TIM->AR = APP_TIM_PERIOD - 1;
    
    nvic_irq_set(APP_TIM_IRQn, 0x01, ENABLE);
    
    intx_disable();
    
    GPIO_PinsRemapConfig(GPIO_Remap_TMR4, ENABLE);
    
    intx_enable();
    
    APP_TIM->CTRL1 |= TMR_CTRL1_CNTEN;
    
    vtask_list_init(&app_tick_task_list, 0);
    
	return 0;
}

/*******************************************************************************
* @brief  app_tick_suspend
* \param[in] none
* \retval: none
*******************************************************************************/
void app_tick_suspend(void)
{
    APP_TIM->DIE = 0;
}

/*******************************************************************************
* @brief  app_tick_resume
* \param[in] none
* \retval: none
*******************************************************************************/
void app_tick_resume(void)
{
    APP_TIM->DIE = TMR_DIE_UEVIE;
}

/*******************************************************************************
* @brief  app_tick_get
* \param[in] none
* \retval: none
*******************************************************************************/
uint32_t app_tick_get(void)
{
    return hal_tick_cnt;
}

/*******************************************************************************
* @brief  app_tick_us_get
* \param[in] none
* \retval: none
*******************************************************************************/
uint32_t app_tick_us_get(void)
{
    uint32_t time_us;
    intx_alloc();
    
    intx_disable();
    
    time_us = hal_tick_cnt * APP_TIM_PERIOD;
    time_us += APP_TIM->CNT;
    
    intx_enable();
    
    return time_us;
}


/*******************************************************************************
* @brief  app_tick_isr
* \param[in] none
* \retval: none
*******************************************************************************/
void app_timer_isr(void)
{
    APP_TIM->STS = 0; 
    hal_tick_cnt++;
    
    vtask_list_run_once(&app_tick_task_list);
}

/*******************************************************************************
* @brief  app_timer_duty_set
* \param[in] ch
* \param[in] duty
* \retval: none
*******************************************************************************/
void app_tick_duty_set(uint8_t ch, uint16_t duty)
{
    switch(ch)
    {
        case 1:
        APP_TIM->CC1 = duty;
        break;
        case 2:
        APP_TIM->CC2 = duty;
        break;
        case 3:
        APP_TIM->CC3 = duty;
        break;
        case 4:
        APP_TIM->CC4 = duty;
        break;
    }
    
}
